19. MC 控制:常量 α(第 2 部分)

MC 控制:常量 α

在之前的练习(练习:增量均值)中,你完成了一种算法,该算法可以不断估算一系列数字 (x_1, x_2, \ldots, x_n) 的均值。running_mean 会接受一系列数字 x 作为输入并返回一个 mean_values 列表,其中 mean_values[k]x[:k+1] 的均值。

当我们在下个部分(MC 控制:策略评估)针对蒙特卡洛控制调整该算法时,序列 (x_1, x_2, \ldots, x_n) 对应的是经历相同状态动作对后获得的回报。

但是,(相同状态动作对)的抽样回报可能对应于很多不同的策略。因为控制算法是由一系列的评估和改进步骤组成,在每个互动阶段后,策略被改进。尤其是,我们提到后续时间步抽取的回报很可能对应的策略更优化。

因此,有必要修改策略评估步骤并改为使用常量步长,我们在上个视频(MC 控制:常量 α(第 1 部分))中表示为 \alpha。这样会确保智能体在估算动作值时主要考虑最近抽样的回报,并逐渐忘记很久之前的回报。

你可以在下方找到类似的伪代码(对一系列 (x_1, x_2, \ldots, x_n) 采取逐渐忘记的的均值)。

此更改已在下面的 forgetful_mean 函数中实现。该函数接受一系列的数字 x 和步长 alpha 作为输入。返回一个列表 mean_values,其中 mean_values[i] 是第 (i+1) 个估算的状态动作值。

print_results 函数会分析 running_meanforgetful_mean 函数之间的差值。它向两个函数传入相同的 x 值并在 forgetful_mean 函数中测试 alpha 的多个值。

请花时间熟悉下面的代码。然后,点击[测试答案]按钮以执行 print_results 函数。如果你想运行更多的测试以加深理解的话,可以随意更改 xalpha_values 的值。

Start Quiz:

import numpy as np

# This is the sequence (corresponding to successively sampled returns). 
# Feel free to change it!
x = np.hstack((np.ones(10), 10*np.ones(10)))

# These are the different step sizes alpha that we will test.  
# Feel free to change it!
alpha_values = np.arange(0,.3,.01)+.01

#########################################################
# Please do not change any of the code below this line. #
#########################################################

def running_mean(x):
    mu = 0
    mean_values = []
    for k in np.arange(0, len(x)):
        mu = mu + (1.0/(k+1))*(x[k] - mu)
        mean_values.append(mu)
    return mean_values
    
def forgetful_mean(x, alpha):
    mu = 0
    mean_values = []
    for k in np.arange(0, len(x)):
        mu = mu + alpha*(x[k] - mu)
        mean_values.append(mu)
    return mean_values

def print_results():
    """
    prints the mean of the sequence "x" (as calculated by the
    running_mean function), along with analogous results for each value of alpha 
    in "alpha_values" (as calculated by the forgetful_mean function).
    """
    print('The running_mean function returns:', running_mean(x)[-1])
    print('The forgetful_mean function returns:')
    for alpha in alpha_values:
        print(np.round(forgetful_mean(x, alpha)[-1],4), \
        '(alpha={})'.format(np.round(alpha,2)))

设置 \alpha 的值

注意,forgetful_mean 函数与常量 \alpha MC 控制中的评估步骤紧密相连。你可以在下方找到相关的伪代码。

在继续学习下个部分之前,请使用上述代码环境验证在实现常量 \alpha MC 控制时如何设置 \alpha 的值。

  • 你应该始终将 \alpha 的值设为大于 0 并小于等于 1 之间的数字。

    • 如果 \alpha=0,则智能体始终不会更新动作值函数估算。
    • 如果 \alpha = 1,则每个状态动作对的最终值估算始终等于智能体(访问该对后)最后体验的回报。
  • 如果 \alpha 的值更小,则促使智能体在计算动作值函数估值时考虑更长的回报历史记录。增加 \alpha 的值确保智能体更侧重于最近抽取的回报。

注意,还可以通过稍微如下所示地改写更新步骤验证上述规律:

Q(S_t,A_t) \leftarrow (1-\alpha)Q(S_t,A_t) + \alpha G_t

现在更明显的是,\alpha 会控制信任最近的回报 G_t(而不是通过考虑所有以前的回报得出的估值 Q(S_t,A_t))的程度。

重要事项:在实现常量 \alpha MC 控制时,必须尽量不要将 \alpha 的值设为太接近 1。因为非常大的值可能会导致算法无法收敛于最优策略 \pi_*。但是,也尽量不要将 \alpha 的值设得太小,因为可能会导致智能体的学习速度太慢。在你的实现中,\alpha 的最佳值将很大程度上取决于你的环境,最好通过试错法得出最佳值。